//
// Created by 吴喆 on 2020/3/24.
//

#include "ParticleGenerator.h"
#include "Playable.h"

ParticleGenerator::ParticleGenerator(Texture2D *texture, Playable *parent,
                                     unsigned int particleCount) : texture(texture),
                                                                   parent(parent),
                                                                   particleCount(particleCount) {
    for (unsigned int i = 0; i < particleCount; ++i) {
        particles.emplace_back(Particle());
    }
}

void ParticleGenerator::update() {
    // Add new particles
    for (unsigned int i = 0; i < newParticlesEachTime; ++i) {
        unsigned int unusedParticle = firstUnusedParticle();
        respawnParticle(particles[unusedParticle], parent, glm::vec2(0, 0.2));
    }

    // Update all particles
    for (unsigned int i = 0; i < particleCount; ++i) {
        Particle &p = particles[i];
        p.life -= CTime::getInstance()->getDelta();
        if (p.life > 0.0f) {   // particle is alive, thus update
            p.position = glm::vec2(p.position.x, p.position.y + p.velocity.y * CTime::getInstance()->getDelta());
            p.color.w -= CTime::getInstance()->getDelta() * 3;
        }
    }
}

unsigned int ParticleGenerator::firstUnusedParticle() {
    // Search from last used particle, this will usually return almost instantly
    for (unsigned int i = lastUsedParticle; i < particleCount; ++i) {
        if (particles[i].life <= 0.0f) {
            lastUsedParticle = i;
            return i;
        }
    }
    // Otherwise, do a linear search
    for (unsigned int i = 0; i < lastUsedParticle; ++i) {
        if (particles[i].life <= 0.0f) {
            lastUsedParticle = i;
            return i;
        }
    }
    // Override first particle if all others are alive
    lastUsedParticle = 0;
    return 0;
}

void ParticleGenerator::respawnParticle(Particle &particle, Playable *object, glm::vec2 offset) {
    GLfloat random = ((rand() % 100) - 50.0) / 300.0f;
    GLfloat rColor = 0.5 + ((rand() % 100) / 100.0f);
    particle.position = glm::vec2(object->currPosition.x, object->currPosition.y + random) + offset;
    particle.color = glm::vec4(rColor, rColor, rColor, 1.0f);
    particle.life = 0.3;
    particle.velocity = glm::vec2(object->speed * 0.1f);
    if (object->direction == DIRECTION::LEFT) {
        particle.position = glm::vec2(object->currPosition.x + object->size.x, object->currPosition.y) + random + offset;
    }
}


void ParticleGenerator::render(Renderer &renderer) {
    for (auto p : particles) {
        if (p.life > 0) {
            renderer.DrawSprite(parent->scene->getCamera(), texture, p.position, glm::vec2(0.5, 0.5), 0.0f, false, false, true, p.color);
        }
    }
}
